package com.yida.gwj.basis.service.impl;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.validation.Validator;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson2.JSONObject;
import com.yida.common.core.exception.ServiceException;
import com.yida.common.core.utils.DateUtils;
import com.yida.common.core.utils.StringUtils;
import com.yida.common.core.utils.bean.BeanValidators;
import com.yida.common.core.utils.poi.ExcelUtil;
import com.yida.common.security.utils.SecurityUtils;
import com.yida.gwj.basis.domain.imp.GwjBaseHouseAndGwjBaseOwnerImp;
import com.yida.gwj.basis.service.IGwjBaseSelfBuiltHousesBusinessService;
import com.yida.gwj.common.constant.GwjCustomImportConstants;
import com.yida.gwj.common.domain.GwjBaseBuild;
import com.yida.gwj.common.domain.GwjBaseCommunity;
import com.yida.gwj.common.domain.GwjBaseHouse;
import com.yida.gwj.common.domain.GwjBaseOwner;
import com.yida.gwj.common.domain.dto.GwjBaseHouseDTO;
import com.yida.gwj.common.domain.request.GwjBaseHouseRequest;
import com.yida.gwj.common.domain.request.GwjBaseOwnerRequest;
import com.yida.gwj.common.service.IGwjBaseBuildService;
import com.yida.gwj.common.service.IGwjBaseCommunityService;
import com.yida.gwj.common.service.IGwjBaseHouseService;
import com.yida.gwj.common.service.IGwjBaseOwnerService;
import com.yida.gwj.common.service.IGwjImpSqeService;

@Service
public class GwjBaseSelfBuiltHousesBusinessServiceImpl implements IGwjBaseSelfBuiltHousesBusinessService {

    private static final Logger log = LoggerFactory.getLogger(GwjBaseSelfBuiltHousesBusinessServiceImpl.class);

    @Autowired
    protected Validator validator;

    @Autowired
    private IGwjBaseCommunityService communityService;

    @Autowired
    private IGwjBaseBuildService buildService;

    @Autowired
    private IGwjBaseHouseService houseService;

    @Autowired
    private IGwjBaseOwnerService ownerService;

    @Autowired
    private IGwjImpSqeService gwjImpSqeService;

    @Autowired
    protected SqlSessionFactory sqlSessionFactory;

    // 20230511 自定义导入楼栋序列名
    private String selfImpBuildSeqName = "selfImpBuild";

    // 20230511 自定义导入房屋序列名
    private String selfImpHouseSeqName = "selfImpHouse";

    @Override
    public List<GwjBaseCommunity> selectGwjBaseCommunityList(GwjBaseCommunity baseCommunity) {
        return communityService.selectGwjBaseCommunityList(baseCommunity);
    }

    @Override
    public List<GwjBaseBuild> selectGwjBaseBuildList(GwjBaseBuild baseBuild) {
        return buildService.selectGwjBaseBuildList(baseBuild);
    }

    @Override
    public List<GwjBaseHouseDTO> queryGwjBaseHouseListByParam(GwjBaseHouseRequest houseRequest) {
        return houseService.queryGwjBaseHouseListByParam(houseRequest);
    }

    @Override
    public List<GwjBaseOwner> selectGwjBaseOwnerList(GwjBaseOwnerRequest ownerRequest) {
        return ownerService.selectGwjBaseOwnerList(ownerRequest);
    }

    @Override
    public String importBaseCommunity(MultipartFile file, boolean updateSupport) throws Exception {
        ExcelUtil<GwjBaseCommunity> util = new ExcelUtil<GwjBaseCommunity>(GwjBaseCommunity.class);
        List<GwjBaseCommunity> baseCommunityList = util.importExcel(file.getInputStream());
        String operName = SecurityUtils.getUsername();
        return importBaseCommunity(baseCommunityList, updateSupport, operName);
    }

    /**
     * 导入基础项目信息
     *
     * @param baseCommunityList 基础项目列表
     * @param isUpdateSupport 是否覆盖
     * @param operName 操作员名称
     * @return
     */
    private String importBaseCommunity(List<GwjBaseCommunity> baseCommunityList, boolean updateSupport, String operName) {
        if (StringUtils.isNull(baseCommunityList) || baseCommunityList.size() == 0) {
            throw new ServiceException("导入项目数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        String areaId = SecurityUtils.getAreaId();
        Long userId = SecurityUtils.getUserId();
        for (GwjBaseCommunity bc : baseCommunityList) {
            if (StringUtils.isEmpty(bc.getCommunityName()) || StringUtils.isNull(bc.getAreaId()) || StringUtils.isNull(bc.getStreetId())) {
                failureMsg.append("导入失败！数据不能存在项目名、地区名、街道名称为空的数据！");
                throw new ServiceException(failureMsg.toString());
            }
            if (userId != 1) {
                if (!areaId.contains(Long.toString(bc.getAreaId()))) {
                    throw new ServiceException("导入失败！当前导入区域不在用户操作范围内！");
                }
            }
            try {
                // BaseCommunity checkBc = communityService.selectCommunityByName(bc.getName());
                GwjBaseCommunity checkBc = communityService.selectGwjBaseCommunityByGwjBaseCommunityName(bc.getCommunityName());
                if (StringUtils.isNull(checkBc)) {
                    BeanValidators.validateWithException(validator, bc);
                    bc.setImportFlag("1");
                    bc.setCreateBy(operName);
                    bc.setCreateTime(DateUtils.getNowDate());
                    // communityService.insertImportCommunity(bc);
                    communityService.insertImportGwjBaseCommunity(bc);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、小区名称： " + bc.getCommunityName() + " 导入新增成功");
                }
                // else {
                // failureNum++;
                // failureMsg.append("<br/>" + failureNum + "、小区名称： " + bc.getName() + " 已存在");
                // }
                else if (updateSupport) {
                    // 存在进行更新
                    bc.setCommunityId(checkBc.getCommunityId());
                    bc.setUpdateBy(operName);
                    bc.setUpdateTime(DateUtils.getNowDate());
                    // communityService.updateImportCommunity(bc);
                    communityService.updateImportGwjBaseCommunity(bc);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、小区名称： " + bc.getCommunityName() + " 导入更新成功");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、小区名称： " + bc.getCommunityName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }

        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Override
    public String importDataBuild(MultipartFile file, boolean updateSupport, Long BaseCommunityId) throws Exception {
        ExcelUtil<GwjBaseBuild> util = new ExcelUtil<GwjBaseBuild>(GwjBaseBuild.class);
        List<GwjBaseBuild> baseBuildList = util.importExcel(file.getInputStream());
        String operName = SecurityUtils.getUsername();
        return importBaseBuild(baseBuildList, updateSupport, operName, BaseCommunityId);
    }

    /**
     * 导入楼栋信息
     *
     * @param BaseBuildList 楼栋项目列表
     * @param updateSupport 是否覆盖
     * @param operName 操作员名称
     * @param baseCommunityId 项目ID
     * @return
     */
    private String importBaseBuild(List<GwjBaseBuild> BaseBuildList, boolean updateSupport, String operName, Long baseCommunityId) {
        if (StringUtils.isNull(baseCommunityId)) {
            throw new ServiceException("项目编号不能为空");
        }
        // 查询项目信息
        GwjBaseCommunity baseCommunity = communityService.selectGwjBaseCommunityByGwjBaseCommunityId(baseCommunityId);
        if (StringUtils.isNull(baseCommunity)) {
            throw new ServiceException("未获取到对应项目信息");
        }
        if (StringUtils.isNull(BaseBuildList) || BaseBuildList.size() == 0) {
            throw new ServiceException("导入楼栋数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        // 地区ID
        Long areaId = baseCommunity.getAreaId();
        // 街道ID
        Long streetId = baseCommunity.getStreetId();
        List<GwjBaseBuild> inBuildData = new ArrayList<GwjBaseBuild>();
        for (GwjBaseBuild bb : BaseBuildList) {
            if (StringUtils.isEmpty(bb.getBuildName()) || StringUtils.isNull(bb.getTotalOwner())) {
                failureMsg.append("导入失败！不能存在楼栋名称、业主总户数为空的数据！");
                throw new ServiceException(failureMsg.toString());
            }
            try {
                // BaseBuild checkBb = buildService.selectBuildByName(bb.getName());
                // BaseBuild checkBb = buildService.selectGwjCommBuildByBuildName(bb.getName());
                GwjBaseBuild checkBb = buildService.selectGwjBaseBuildByBuildName(bb.getBuildName());
                if (StringUtils.isNull(checkBb)) {
                    BeanValidators.validateWithException(validator, bb);
                    // 设置项目ID
                    bb.setCommunityId(baseCommunityId);

                    // 进行插入转换(imp+id)
                    bb.setProjectCode(GwjCustomImportConstants.SELFBUILTHOUSES + Long.toString(baseCommunityId));
                    // 自然幢号
                    bb.setBuildNo(bb.getBuildName());
                    bb.setBuildType(0);
                    bb.setAreaId(areaId);
                    bb.setStreetId(streetId);
                    // 20230223 是否自建
                    bb.setImportFlag("1");
                    bb.setCreateBy(operName);
                    bb.setCreateTime(DateUtils.getNowDate());
                    inBuildData.add(bb);
                } else if (updateSupport) {
                    bb.setBuildId(checkBb.getBuildId());
                    bb.setUpdateBy(operName);
                    bb.setUpdateTime(DateUtils.getNowDate());
                    // buildService.updateImportBuild(bb);
                    buildService.updateImportGwjCommBuild(bb);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、楼栋名称： " + bb.getBuildName() + " 导入更新成功");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、楼栋名称： " + bb.getBuildName() + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        // 操作导入楼栋
        importBuildList(inBuildData, successNum, failureNum, successMsg, failureMsg);
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    /**
     * 新增导入楼栋数据
     *
     * @param inBuildData 楼栋数据
     * @param successNum 成功数
     * @param failureNum 失败数
     * @param successMsg 成功信息
     * @param failureMsg 失败信息
     */
    private void importBuildList(List<GwjBaseBuild> inBuildData, int successNum, int failureNum, StringBuilder successMsg, StringBuilder failureMsg) {
        if (inBuildData != null && inBuildData.size() > 0) {
            // 按导入数据量预约序列长度
            Integer size = inBuildData.size();
            // 预定返回后的第一个序列
            Long startSqe = gwjImpSqeService.reserveSqeByIndex(selfImpBuildSeqName, size.longValue());
            if (startSqe == -1) {
                throw new ServiceException("未获取到操作序列权限！请稍后重试！");
            }
            for (GwjBaseBuild bb : inBuildData) {
                try {
                    // 进行插入转换
                    bb.setBuildCode(GwjCustomImportConstants.SELFBUILTHOUSES + Long.toString(startSqe));
                    // buildService.insertImportBuild(bb);
                    buildService.insertImportGwjCommBuild(bb);
                    startSqe++;
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、楼栋名称： " + bb.getBuildName() + " 导入新增成功");
                } catch (Exception e) {
                    failureNum++;
                    String msg = "<br/>" + failureNum + "、楼栋名称： " + bb.getBuildName() + " 导入失败：";
                    failureMsg.append(msg + e.getMessage());
                    log.error(msg, e);
                }
            }
        }
    }

    @Override
    public String importDataHouseAndOwner(MultipartFile file, boolean updateSupport, Long[] buildIds) throws Exception {
        Map<String, GwjBaseBuild> buildsMap = getBuildListToMap(buildIds);
        if (StringUtils.isEmpty(buildsMap)) {
            throw new ServiceException("未获取到对于楼栋数据，请核对后再导入");
        }
        return processImportDataHouseAndOwner(file, updateSupport, buildsMap);
    }

    @Override
    public String importDataHouseAndOwner(MultipartFile file, boolean updateSupport, Long communityId) throws Exception {
        Map<String, GwjBaseBuild> buildsMap = getBuildListToMap(communityId);
        if (StringUtils.isEmpty(buildsMap)) {
            throw new ServiceException("未获取到对于项目下的楼栋数据，请核对后再导入");
        }
        return processImportDataHouseAndOwner(file, updateSupport, buildsMap);

    }

    /**
     * 操作导入房屋和业主数据
     *
     * @param file 导入文件
     * @param updateSupport 是否覆盖
     * @param buildsMap 楼栋组
     * @return
     * @throws Exception
     * @throws IOException
     */
    private String processImportDataHouseAndOwner(MultipartFile file, boolean updateSupport, Map<String, GwjBaseBuild> buildsMap) throws Exception {
        ExcelUtil<GwjBaseHouseAndGwjBaseOwnerImp> util = new ExcelUtil<GwjBaseHouseAndGwjBaseOwnerImp>(GwjBaseHouseAndGwjBaseOwnerImp.class);
        InputStream is = file.getInputStream();
        List<GwjBaseHouseAndGwjBaseOwnerImp> gwjBaseHouseAndGwjBaseOwnerList = util.importExcel(is);
        // 获取到后关闭流
        if (is != null) {
            is.close();
        }
        // 操作员
        String userName = SecurityUtils.getUsername();
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        // 缓存新增组
        List<GwjBaseHouse> inHouseData = new ArrayList<GwjBaseHouse>();
        List<GwjBaseOwner> inOwnerData = new ArrayList<GwjBaseOwner>();
        // 缓存更新组
        List<GwjBaseHouse> upHouseData = new ArrayList<GwjBaseHouse>();
        List<GwjBaseOwner> upOwnerData = new ArrayList<GwjBaseOwner>();
        for (GwjBaseHouseAndGwjBaseOwnerImp hao : gwjBaseHouseAndGwjBaseOwnerList) {
            if (StringUtils.isEmpty(hao.getBuildName()) || StringUtils.isEmpty(hao.getLocation()) || StringUtils.isEmpty(hao.getRoomNum()) || StringUtils.isEmpty(hao.getUseType()) || StringUtils.isNull(hao.getForecastSize()) || StringUtils.isNull(hao.getActualSize()) || StringUtils.isEmpty(hao.getOwnerName()) || StringUtils.isEmpty(hao.getCardNum()) || StringUtils.isEmpty(hao.getPhone())) {
                failureMsg.append(hao.getBuildName() + "[" + hao.getRoomNum() + "]" + "导入失败！必填项数据不能为空！");
                throw new ServiceException(failureMsg.toString());
            }
            // 检测当前楼栋名称是否存在
            GwjBaseBuild checkBb = buildsMap.get(hao.getBuildName());
            if (StringUtils.isNull(checkBb)) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、楼栋名称： " + hao.getBuildName() + " 不存在;房屋[" + hao.getRoomNum() + "]导入失败");
                continue;
            }
            try {
                // 校验导入参数
                BeanValidators.validateWithException(validator, hao);
                // 1新建房屋
                GwjBaseHouse bh = new GwjBaseHouse();
                // 设置楼栋标识码
                bh.setBuildCode(checkBb.getBuildCode());
                // // 设置房屋标识码
                // bh.setHouseCode(CustomImportConstants.SELFBUILTHOUSES);
                // 设置地区
                bh.setAreaId(checkBb.getAreaId());
                // 设置街道
                bh.setStreetId(checkBb.getStreetId());
                // 坐落
                bh.setHouseLocation(hao.getLocation());
                // 房屋号
                bh.setRoomNum(hao.getRoomNum());
                // 用途
                bh.setUseType(hao.getUseType());
                // 预测面积
                bh.setForecastSize(hao.getForecastSize());
                // 实测面积
                bh.setActualSize(hao.getActualSize());
                // 产权证书号
                bh.setCertificateNum(hao.getCertificateNum());
                // 20230223 是否自建导入
                bh.setImportFlag("1");
                System.out.println("bh:" + JSONObject.from(bh));
                // 2新建业主
                GwjBaseOwner bo = new GwjBaseOwner();
                // 设置地区
                bo.setAreaId(checkBb.getAreaId());
                // 设置街道
                bo.setStreetId(checkBb.getStreetId());
                // 名称
                bo.setOwnerName(hao.getOwnerName());
                // 身份证号
                bo.setCardNum(hao.getCardNum());
                // 手机号
                bo.setOwnerPhone(hao.getPhone());
                // 20230223 是否自建导入
                bo.setImportFlag("1");
                System.out.println("bo:" + JSONObject.from(bo));
                // 查看坐落是否存在[增加楼栋编号进行定位]
                GwjBaseHouse checkBh = houseService.selectGwjBaseHouseByLocation(hao.getLocation(), checkBb.getBuildCode());
                if (StringUtils.isNull(checkBh)) {
                    // 设置新增人员
                    bh.setCreateBy(userName);
                    bo.setCreateBy(userName);
                    inHouseData.add(bh);
                    inOwnerData.add(bo);

                    // 新增
                    if (inHouseData.size() == 100 && inOwnerData.size() == 100) {
                        saveImportHouseAndOwner(inHouseData, inOwnerData);
                        inHouseData.clear();
                        inOwnerData.clear();
                    }
                    // successNum++;
                    // successMsg.append("<br/>" + successNum + "、坐落： " + bh.getLocation() + "，户主："
                    // +bo.getName()+"导入成功");
                } else if (updateSupport) {
                    // 房屋更新则进行值替换
                    bh.setHouseId(checkBh.getHouseId());
                    bh.setHouseCode(checkBh.getHouseCode());
                    bh.setUpdateBy(userName);
                    // 业主更新则进行值替换
                    bo.setHouseCode(checkBh.getHouseCode());
                    bo.setUpdateBy(userName);
                    upHouseData.add(bh);
                    upOwnerData.add(bo);
                    // 修改
                    if (upHouseData.size() == 100 && upOwnerData.size() == 100) {
                        upImportHouseAndOwner(upHouseData, upOwnerData);
                        upHouseData.clear();
                        upOwnerData.clear();
                    }
                    // successNum++;
                    // successMsg.append("<br/>" + successNum + "、坐落： " + bh.getLocation() + "，户主："
                    // +bo.getName()+"更新成功");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、楼栋： " + checkBb.getBuildName() + ",房屋和业主数据导入失败：";
                log.error(msg, e);
            }
        }
        // 对余留数据进行新增
        if (inHouseData.size() > 0 && inOwnerData.size() > 0) {
            saveImportHouseAndOwner(inHouseData, inOwnerData);
        }
        // 对余留数据进行修改
        if (upHouseData.size() > 0 && upOwnerData.size() > 0) {
            upImportHouseAndOwner(upHouseData, upOwnerData);
        }
        if (failureNum > 0) {
            throw new ServiceException("很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确");
        } else {
            // successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
            successMsg.insert(0, "恭喜您，数据已全部导入成功！");
        }
        return successMsg.toString();
    }

    /**
     * 保存导入的房屋和业主
     *
     * @param inHouseData
     * @param inOwnerData
     */
    // private void saveImportHouseAndOwner(List<BaseHouse>
    // inHouseData,List<BaseOwner> inOwnerData,int successNum ,int
    // failureNum,StringBuilder successMsg ,StringBuilder failureMsg) {
    private void saveImportHouseAndOwner(List<GwjBaseHouse> inHouseData, List<GwjBaseOwner> inOwnerData) {
        if ((StringUtils.isNull(inHouseData) && inHouseData.size() == 0) || (StringUtils.isNull(inOwnerData) && inOwnerData.size() == 0)) {
            return;
        }
        // 操作员
        String userName = SecurityUtils.getUsername();
        // 按导入数据量预约序列长度
        Integer size = inHouseData.size();
        // 预定返回后的第一个序列
        Long startSqe = gwjImpSqeService.reserveSqeByIndex(selfImpHouseSeqName, size.longValue());
        if (startSqe == -1) {
            throw new ServiceException("未获取到操作序列权限！请稍后重试！");
        }
        // 设置ExecutorType.BATCH原理：把SQL语句发个数据库，数据库预编译好，数据库等待需要运行的参数，接收到参数后一次运行，ExecutorType.BATCH只打印一次SQL语句，多次设置参数步骤
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            for (int i = 0; i < inHouseData.size(); i++) {

                String houseCode = GwjCustomImportConstants.SELFBUILTHOUSES + startSqe.toString();
                inHouseData.get(i).setHouseCode(houseCode);
                inOwnerData.get(i).setHouseCode(houseCode);
                startSqe++;
            }
            houseService.insertImportGwjBaseHouse(inHouseData);
            ownerService.insertImportGwjBaseOwner(inOwnerData);
            session.commit();
        } catch (Exception e) {
            session.rollback();
            // throw new ServiceException("未获取到对于项目下的楼栋数据，请核对后再导入");
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    /**
     * 修改导入的房屋和业主
     *
     * @param inHouseData
     * @param inOwnerData
     */
    private void upImportHouseAndOwner(List<GwjBaseHouse> inHouseData, List<GwjBaseOwner> inOwnerData) {
        if ((StringUtils.isNull(inHouseData) && inHouseData.size() == 0) || (StringUtils.isNull(inOwnerData) && inOwnerData.size() == 0)) {
            return;
        }
        // 设置ExecutorType.BATCH原理：把SQL语句发个数据库，数据库预编译好，数据库等待需要运行的参数，接收到参数后一次运行，ExecutorType.BATCH只打印一次SQL语句，多次设置参数步骤
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            houseService.updateImportGwjBaseHouse(inHouseData);
            // for(int i=0;i<inHouseData.size();i++) {
            // inOwnerData.get(i).setHouseCode(inHouseData.get(i).getHouseCode());
            // }
            ownerService.updateImportGwjBaseOwner(inOwnerData);
            session.commit();
        } catch (Exception e) {
            // throw new ServiceException("未获取到对于项目下的楼栋数据，请核对后再导入");
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    /**
     * 根据项目ID查询楼栋组
     *
     * @param communityId 项目ID
     * @return
     */
    private Map<String, GwjBaseBuild> getBuildListToMap(Long communityId) {
        // List<BaseBuild> list = buildService.selectGwjCommBuildListByCommunityId(communityId);
        List<GwjBaseBuild> list = buildService.selectGwjBaseBuildListByCommunityId(communityId);
        if (list != null && list.size() > 0) {
            // 根据name进行转换key=name;value=BaseBuild，重复默认保留前一位
            return list.stream().collect(Collectors.toMap(GwjBaseBuild::getBuildName, Function.identity(), (oldValue, newValue) -> oldValue));
        }
        return null;
    }

    /**
     * 根据楼栋ID组查询楼栋组
     *
     * @param buildIds 楼栋ID组
     * @return
     */
    private Map<String, GwjBaseBuild> getBuildListToMap(Long[] buildIds) {
        Map<String, GwjBaseBuild> resultMap = new HashMap<String, GwjBaseBuild>();
        List<String> buildsList = groupBuilds(buildIds);
        for (String str : buildsList) {
            // List<BaseBuild> list = buildService.selectBuildByIds(str);
            // List<BaseBuild> list = buildService.selectGwjCommBuildByBuildIds(str);
            List<GwjBaseBuild> list = buildService.selectGwjBaseBuildByBuildIds(str);
            if (list != null && list.size() > 0) {
                resultMap.putAll(list.stream().collect(Collectors.toMap(GwjBaseBuild::getBuildName, Function.identity(), (oldValue, newValue) -> oldValue)));
            }
        }
        return resultMap.size() > 0 ? resultMap : null;
    }

    /**
     * 每10条进行一次分组
     *
     * @param buildIds 楼栋ID组
     * @return
     */
    private List<String> groupBuilds(Long[] buildIds) {
        List<String> list = new ArrayList<String>();
        boolean groups = false;
        int index = 0;
        if (buildIds.length > 10) {
            groups = true;
            index = 10;
        }
        int buidlIdsLength = buildIds.length;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buidlIdsLength; i++) {
            if (groups) {
                if (index == 0) {
                    sb = new StringBuffer();
                    index = 10;
                }
            }
            if (i != 0 && index != 10) {
                sb.append(",");
            }
            sb.append(buildIds[i]);
            if (index > 0) {
                index--;
            }
            if (index == 0) {
                list.add(sb.toString());
            } else {
                if ((i + 1) == buildIds.length) {
                    list.add(sb.toString());
                }
            }
        }
        return list;
    }

    /**
     * 流式分组，10~100数据量测试83,129,86,84性能偏低，对比for:47,61,51,55平均转化率低于30 数据量不足百万级别暂时不用，并行及高并发情况下参考parallelStream处理。可读性高
     * 
     * @param buildIds 楼栋ID组
     * @param index 分组量
     * @return
     */
    // private List<String> groupBuilds(Long[] buildIds,int index) {
    // List<Long> buildIdList = Arrays.stream(buildIds).collect(Collectors.toList());
    // int limit = (buildIdList.size() + index - 1) / index;
    // List<String> mgList = new ArrayList<String>();
    // Stream.iterate(0, n -> n + 1).limit(limit).forEach(i -> {
    // mgList.add(buildIdList.stream().skip(i * index).limit(index).collect(Collectors.toList()).toString());
    // });
    // return mgList;
    // }

    @Override
    public int removeCommunitys(Long[] communityIds) {
        for (Long communityId : communityIds) {
            // if (buildService.hasBuildByCommunityId(communityId)) {
            // throw new ServiceException("编号：[" + communityId + "]项目下存在楼栋，请先删除楼栋后再操作！");
            // }
            if (buildService.hasGwjBaseBuildByCommunityId(communityId)) {
                throw new ServiceException("编号：[" + communityId + "]项目下存在楼栋，请先删除楼栋后再操作！");
            }
        }
        // return communityService.deleteCommunityByIds(communityIds);
        return communityService.deleteGwjBaseCommunityByGwjBaseCommunityIds(communityIds);
    }

    @Override
    public int removeBuilds(String[] buildCodes) {
        for (String buildCode : buildCodes) {
            if (houseService.hasGwjBaseHouseByBuildCode(buildCode)) {
                throw new ServiceException("编号：[" + buildCode + "]楼栋下存在房屋，请先删除房屋后再操作！");
            }
        }
        // return buildService.deleteBuildByBuildCodes(buildCodes);
        return buildService.deleteGwjBaseBuildByGwjBaseBuildCodes(buildCodes);
    }

    @Override
    public int removeHouses(String[] houseCodes) {
        ownerService.deleteGwjBaseOwnerByHouseCodes(houseCodes);
        houseService.deleteGwjBaseHouseByHouseCodes(houseCodes);
        return 1;
    }

    /* 
     * 20230802
     */
    @Override
    public String importDataHouseAndOwner(MultipartFile file, boolean updateSupport, Long areaId, Long communityId, String buildCode) throws Exception {
        // TODO Auto-generated method stub
        // 获取对应楼栋信息
        GwjBaseBuild gbb = buildService.selectGwjBaseBuildByAreaIdAndBuildCode(areaId, buildCode);
        if (StringUtils.isNull(gbb)) {
            throw new ServiceException("未获取到对应地区下楼栋标识码为[" + buildCode + "]楼栋");
        }
        return processImportDataHouseAndOwner(file, updateSupport, gbb);
    }

    /**
     * 操作导入房屋和业主数据
     *
     * @param file 导入文件
     * @param updateSupport 是否覆盖
     * @param buildsMap 楼栋组
     * @return
     * @throws Exception
     * @throws IOException
     */
    private String processImportDataHouseAndOwner(MultipartFile file, boolean updateSupport, GwjBaseBuild gbb) throws Exception {
        ExcelUtil<GwjBaseHouseAndGwjBaseOwnerImp> util = new ExcelUtil<GwjBaseHouseAndGwjBaseOwnerImp>(GwjBaseHouseAndGwjBaseOwnerImp.class);
        List<GwjBaseHouseAndGwjBaseOwnerImp> gwjBaseHouseAndGwjBaseOwnerList = util.importExcel(file.getInputStream());

        // 操作员
        String userName = SecurityUtils.getUsername();
        // int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        // 缓存新增组
        List<GwjBaseHouse> inHouseData = new ArrayList<GwjBaseHouse>();
        List<GwjBaseOwner> inOwnerData = new ArrayList<GwjBaseOwner>();
        // 缓存更新组
        List<GwjBaseHouse> upHouseData = new ArrayList<GwjBaseHouse>();
        List<GwjBaseOwner> upOwnerData = new ArrayList<GwjBaseOwner>();
        for (GwjBaseHouseAndGwjBaseOwnerImp hao : gwjBaseHouseAndGwjBaseOwnerList) {
            if (StringUtils.isEmpty(hao.getBuildName()) || StringUtils.isEmpty(hao.getLocation()) || StringUtils.isEmpty(hao.getRoomNum()) || StringUtils.isEmpty(hao.getUseType()) || StringUtils.isNull(hao.getForecastSize()) || StringUtils.isNull(hao.getActualSize()) || StringUtils.isEmpty(hao.getOwnerName()) || StringUtils.isEmpty(hao.getCardNum()) || StringUtils.isEmpty(hao.getPhone())) {
                failureMsg.append(hao.getBuildName() + "[" + hao.getRoomNum() + "]" + "导入失败！必填项数据不能为空！");
                throw new ServiceException(failureMsg.toString());
            }
            // 检测当前楼栋名称是否存在
            // GwjBaseBuild checkBb = buildsMap.get(hao.getBuildName());
            if (!hao.getBuildName().equals(gbb.getBuildName())) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、楼栋名称： " + hao.getBuildName() + " 与当前导入楼栋名称[" + gbb.getBuildName() + "]不一致;房屋[" + hao.getRoomNum() + "]导入失败");
                // continue;
                // 这里改为阻断
                throw new ServiceException(failureMsg.toString());
            }
            try {
                // 校验导入参数
                BeanValidators.validateWithException(validator, hao);
                // 1新建房屋
                GwjBaseHouse bh = new GwjBaseHouse();
                // 设置楼栋标识码
                bh.setBuildCode(gbb.getBuildCode());
                // // 设置房屋标识码
                // bh.setHouseCode(CustomImportConstants.SELFBUILTHOUSES);
                // 设置地区
                bh.setAreaId(gbb.getAreaId());
                // 设置街道
                bh.setStreetId(gbb.getStreetId());
                // 坐落
                bh.setHouseLocation(hao.getLocation());
                // 房屋号
                bh.setRoomNum(hao.getRoomNum());
                // 用途
                bh.setUseType(hao.getUseType());
                // 预测面积
                bh.setForecastSize(hao.getForecastSize());
                // 实测面积
                bh.setActualSize(hao.getActualSize());
                // 产权证书号
                bh.setCertificateNum(hao.getCertificateNum());
                // 20230223 是否自建导入
                bh.setImportFlag("1");
                // System.out.println("bh:" + JSONObject.from(bh));
                // 2新建业主
                GwjBaseOwner bo = new GwjBaseOwner();
                // 设置地区
                bo.setAreaId(gbb.getAreaId());
                // 设置街道
                bo.setStreetId(gbb.getStreetId());
                // 名称
                bo.setOwnerName(hao.getOwnerName());
                // 身份证号
                bo.setCardNum(hao.getCardNum());
                // 手机号
                bo.setOwnerPhone(hao.getPhone());
                // 20230223 是否自建导入
                bo.setImportFlag("1");
                // System.out.println("bo:" + JSONObject.from(bo));
                // 查看坐落是否存在[增加楼栋编号进行定位]
                GwjBaseHouse checkBh = houseService.selectGwjBaseHouseByLocation(hao.getLocation(), gbb.getBuildCode());
                if (StringUtils.isNull(checkBh)) {
                    // 设置新增人员
                    bh.setCreateBy(userName);
                    bo.setCreateBy(userName);
                    inHouseData.add(bh);
                    inOwnerData.add(bo);

                    // 新增
                    if (inHouseData.size() == 100 && inOwnerData.size() == 100) {
                        saveImportHouseAndOwner(inHouseData, inOwnerData);
                        inHouseData.clear();
                        inOwnerData.clear();
                    }
                    // successNum++;
                    // successMsg.append("<br/>" + successNum + "、坐落： " + bh.getLocation() + "，户主："
                    // +bo.getName()+"导入成功");
                } else if (updateSupport) {
                    // 房屋更新则进行值替换
                    bh.setHouseId(checkBh.getHouseId());
                    bh.setHouseCode(checkBh.getHouseCode());
                    bh.setUpdateBy(userName);
                    // 业主更新则进行值替换
                    bo.setHouseCode(checkBh.getHouseCode());
                    bo.setUpdateBy(userName);
                    upHouseData.add(bh);
                    upOwnerData.add(bo);
                    // 修改
                    if (upHouseData.size() == 100 && upOwnerData.size() == 100) {
                        upImportHouseAndOwner(upHouseData, upOwnerData);
                        upHouseData.clear();
                        upOwnerData.clear();
                    }
                    // successNum++;
                    // successMsg.append("<br/>" + successNum + "、坐落： " + bh.getLocation() + "，户主："
                    // +bo.getName()+"更新成功");
                }
            } catch (Exception e) {
                failureNum++;
                String msg = "<br/>" + failureNum + "、楼栋： " + gbb.getBuildName() + ",房屋和业主数据导入失败：";
                log.error(msg, e);
            }
        }
        // 对余留数据进行新增
        if (inHouseData.size() > 0 && inOwnerData.size() > 0) {
            saveImportHouseAndOwner(inHouseData, inOwnerData);
        }
        // 对余留数据进行修改
        if (upHouseData.size() > 0 && upOwnerData.size() > 0) {
            upImportHouseAndOwner(upHouseData, upOwnerData);
        }
        if (failureNum > 0) {
            throw new ServiceException("很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确");
        } else {
            // successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
            successMsg.insert(0, "恭喜您，数据已全部导入成功！");
        }
        return successMsg.toString();
    }

}
